Multi Rows or Items in a form

Read Basic Form topics before reading this topics

  • In controller

    Step1: import FormBuilder, FormGroup , FormControl in controller

    
                 import { FormBuilder, FormGroup, Validators, FormArray, FormControl, NgForm } from '@angular/forms';
                 

    Step2: declare FormGroup & orderItems variables

    
                           
    
                      orderForm: FormGroup; 
                      orderItems: any;                 
                  
    
                

    Step 3: injust FormBuilder into constructor()

    
                constructor(private fb: FormBuilder){ }
                  

    Step4: define orderForm

    
                  this.orderForm = this.fb.group({
                        'id': [''],
                        'order_date': [''], 
                        'customer_id': [''], 
                        'orderItems': this.fb.array([ ]),
                  }); 
                  
                  

    Step5: define orderItems

    
                  createItemFormGroup(): FormGroup {
                          return this.fb.group({
                              orderId: [''],
                              itemCode: [''],
                              itemName: [''],
                              price: ['']
                             
                          });
                      }
                

    Step6: add the multiple row to the orderForm

    
                      onAddRow() {                    
                        this.orderItems = this.orderForm.get('orderItems') as FormArray;
                        this.orderItems.push(this.createItemFormGroup({}));
                      }
                    
    1) createItemFormGroup() is defined in Step5
    2) onAddRow() is called from html(View)

    Step7: remove item

    
                        onRemoveRow(rowIndex: number) { 
                          this.orderItems.removeAt(rowIndex); 
                      }
                    
    onRemoveRow() is called from html

  • In View page

    Step1: add form tag

    
                      <form [formGroup]="orderForm" (ngSubmit)="onSubmit()" autocomplete="off">
                          ... 
                          ....
                      </form>
                    

    Step2: add form elements

    Add form elements and link with formGroup

    Code

     
    
                     <form [formGroup]="orderForm" (ngSubmit)="onSubmit()" autocomplete="off">
    
    
                          <div class="col-sm-3">
                              <label>Customer<span style="color:red;">*</span></label>
                              <select class="form-control" formControlName="customer_id" >
                                  <option  selected>Select </option>
                                  <option *ngFor="let row of customersData" [value]="row.id">{row.customer_name}</option>
                              </select>
                              
                          </div>
    
    
                    </form>
    
                    

    Step 3: add multiple row elements

    1) looping the orderItems : *ngFor="let row of orderForm.get('orderItems')?.controls;let index = index;"
    2) link formElements in the loop : [formControl]="row.get('itemCode')"

    Code

    
                        <table>
                            <tr *ngFor="let row of orderForm.get('orderItems')?.controls;let index = index;">
                                    <td style="width:20%">
                                        <div style="position:relative">
                                            <input type="text" class="form-control"  [formControl]="row.get('itemCode')">
                                            
                                        </div>
                                    </td>
    
                                    <td style="width:20%" >
                                    <div style="position:relative">
                                            <input type="text" class="form-control"  [formControl]="row.get('itemName')">
                                            
                                    </div>
                                    </td>
                            </tr>
                        </table>
                        
    
                    

    Step 4: add button to append new row

    
                    <button  class="btn btn-sm " type="button" (click)="onAddRow()"><i class="fa fa-plus-circle"  ></i>&nbsp; Add New Item</button>
      
                    

    Step5 : add button to delete a row

    
                    <i  class="fa fa-times" (click)="onRemoveRow(index)" id="remove_{index}" style="display:block"></i>Delete
                    

  • Additional Features

    set/get multi-row variables based on index in components

    
                    //set
                    ((this.itemForm.get('addItemsRequests') as FormArray).at(index) as FormGroup).get('itemCode').patchValue('123');
    
                    //get
                    var code = this.itemForm.get('addItemsRequests')?.value[rowIndex].itemCode;
    
    
                 

    Loop the multi-rows in component (set / get in the loop)

    
    
                    let orderItems=((this.itemForm.get('addItemsRequests') as FormArray));
                    let sum=0;
                    orderItems.controls.forEach(x => {
                        // get 
                        var itemtotal=x.get('total').value;
    
                        sum=sum+parseFloat(itemtotal);
                        this.orderForm.get('grandTotal').patchValue(sum);
    
                        //set 
                        x.patchValue(
                                {total:120}
                            );
                    });
                 

    Pre-populate data into multi-row form

    FormGroup
                     
                        
                         this.orderForm = this.formBuilder.group({
                            sohdrId: [0],
                            orgId: ['', Validators.required],
                            customerId: ['', Validators.required],
                          
                            salesOrderDtls: this.formBuilder.array([ ])
                        });
                                      
                 
    Pass object to formArray
    
    
                    createItem(item:any): FormGroup {
            
                        return this.formBuilder.group({
                            itemId: item.itemid,
                            orgId:this.orgId,
                            itemCode:[item.itemCode, Validators.required],
                            itemName:[item.itemName],
                            quantity: [item.qtyRequired, Validators.required],
                            expectedDate: [item.expectedDate],
                            basePrice:item.basePrice,
                            total:[item.total, Validators.required],
                            uomName:item.uomName,
                            minOrderQty:item.minOrderQty,
                
                        });
                      }
    
    
                      //pass empty object for new entry
                      addItem(): void {
                        this.items = this.orderForm.get('salesOrderDtls') as FormArray;
                        this.items.push(this.createItem({}));
                      }
    
    
                 
    Loop the API data
    
    
                    this.orderService.getDetails(this.orderId,this.orgId)
                        .subscribe(data => {
    
                                    //start loop
                                    data.salesOrderitems.forEach(row => { 
    
                                                    //get formArray
                                                    this.items = this.orderForm.get('salesOrderDtls') as FormArray; 
                                                
                                                    this.items.push(this.createItem(
                                                    {
                                                        itemid:row.itemid,
                                                        itemCode:row.itemCode,
                                                        itemName: row.itemName,
                                                        basePrice:row.basePrice,
                                                        uomName:row.uomName,
                                                        minOrderQty:row.minOrderQty,
                                                        expectedDate:expectedDate,
                                                        qtyRequired:row.qtyRequired,
                                                        total:total
                                    
                                                    }
                                                    ));
                        
                                        
                        
                                    });
    
                        });                 
                 

    Clear FormArray item

    
                 (this.orderForm.controls['salesOrderDtls'] as FormArray).clear();